package tools

// 创建显示 label 的函数类型
type TParentTreeLabelCall func(data map[string]any) string
type TParentTreeLeafShowCall func(data map[string]any) bool

type ParentTree struct {
	Data         []map[string]any
	RootVal      any
	IdFlag       string
	PidFlag      string
	LabelCall    TParentTreeLabelCall
	LeafShowCall TParentTreeLeafShowCall // 叶子节点是否显示
}

type ParentTreeData struct {
	Key      any              `json:"key,omitempty"`
	Label    any              `json:"label,omitempty"`
	Data     map[string]any   `json:"data"`
	Children []ParentTreeData `json:"children"`
}

// 创建 tree-map 工具
func NewParentTree() *ParentTree {
	return &ParentTree{}
}

// 设置顶级标志值
func (tm *ParentTree) SetRootVal(val any) *ParentTree {
	tm.RootVal = val
	return tm
}

// 设置主 id 字段名
func (tm *ParentTree) SetIdFlag(flag string) *ParentTree {
	tm.IdFlag = flag
	return tm
}

// 设置上级 id 字段名
func (tm *ParentTree) SetPidFlag(flag string) *ParentTree {
	tm.PidFlag = flag
	return tm
}

// 设置叶子节点是否显示
func (tm *ParentTree) SetLeafShowCall(leafShowCall TParentTreeLeafShowCall) *ParentTree {
	tm.LeafShowCall = leafShowCall
	return tm
}

// 设置上级 id 字段名
func (tm *ParentTree) SetLabelCall(labelCall TParentTreeLabelCall) *ParentTree {
	tm.LabelCall = labelCall
	return tm
}

// 设置原始数据
func (tm *ParentTree) SetData(data []map[string]any) *ParentTree {
	tm.Data = data
	return tm
}

// 生成 label 显示字符串
func (tm *ParentTree) generateLabel(data map[string]any) any {
	if tm.LabelCall != nil {
		return tm.LabelCall(data)
	}
	return nil
}

// 解析树形数据
func (tm *ParentTree) parseTree(data *[]map[string]any, pid any) []ParentTreeData {
	td := []ParentTreeData{}
	for _, d := range *data {
		if d[tm.PidFlag] == pid {
			// 属于该级树， 计算子树
			children := []ParentTreeData{}
			if pid, ok := d[tm.IdFlag]; ok {
				// 存在主键标识， 计算下级树
				children = tm.parseTree(data, pid)
			}
			if tm.LeafShowCall == nil {
				td = append(td, ParentTreeData{
					Key:      d[tm.IdFlag],
					Label:    tm.generateLabel(d),
					Data:     d,
					Children: children,
				})
			} else if len(children) > 0 || tm.LeafShowCall(d) {
				td = append(td, ParentTreeData{
					Key:      d[tm.IdFlag],
					Label:    tm.generateLabel(d),
					Data:     d,
					Children: children,
				})
			}
		}
	}
	return td
}

// 获取树形结构数据
func (tm *ParentTree) GetTreeData() []ParentTreeData {
	return tm.parseTree(&tm.Data, tm.RootVal)
}
